// Copyright (C) 1953-2023 NUDT
// Verilog module name - info_extract   
// Version: V4.3.0.20230309
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//          
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module info_extract(
    i_clk               ,
    i_rst_n             ,
    
    iv_data             ,
    i_data_wr           ,
	 iv_ipv              ,
    iv_inject_dbufid    ,
    
    ov_data                 ,
    o_data_wr               ,
    ov_inject_dbufid        ,
    ov_ipv                  ,
    o_replication_flag      ,
    o_ctag_flag    
);
// I/O
// clk & rst
input                   i_clk  ;
input                   i_rst_n;
//input 
input       [8:0]       iv_data  ;
input                   i_data_wr;
input       [2:0]       iv_ipv   ;
input       [4:0]       iv_inject_dbufid;
//output
output  reg [8:0]       ov_data             ;
output  reg             o_data_wr           ;
output  reg [4:0]       ov_inject_dbufid    ;
output  reg [2:0]       ov_ipv              ;
output  reg             o_replication_flag  ;
output  reg             o_ctag_flag          ;
//***************************************************
//   add valid of data and delay 14 cycles
//***************************************************
//internal wire
reg         [170:0]     rv_data;
reg         [10:0]      rv_byte_cnt; 
always @(posedge i_clk or negedge i_rst_n) begin
    if(!i_rst_n) begin
        rv_data      <= 171'b0;
        rv_byte_cnt  <= 11'b0;
    end
    else begin
        if(i_data_wr)begin
            rv_byte_cnt <= rv_byte_cnt +1'b1;
            rv_data     <= {rv_data[161:0],iv_data};
        end
        else begin
            rv_data     <= {rv_data[161:0],9'b0};  
            rv_byte_cnt <= 11'b0;           
        end
    end
end  
//***************************************************
//               info extract
//***************************************************    
reg         [1:0]       rv_extract_state;
localparam  IDLE_S             = 2'd0,
            TRAN_PKT_S         = 2'd1;          
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        ov_data             <= 9'b0;
        o_data_wr           <= 1'b0;
        ov_inject_dbufid    <= 5'b0;
        ov_ipv              <= 3'b0;
        o_replication_flag  <= 1'b0;
        o_ctag_flag          <= 1'b0;
 
        rv_extract_state    <= IDLE_S;
    end
    else begin
        case(rv_extract_state)
            IDLE_S:begin
                if(rv_byte_cnt == 11'd19)begin                  
                    o_data_wr           <= 1'b1;
                    ov_data             <= rv_data[170:162];
 
                    rv_extract_state    <= TRAN_PKT_S;                     
                    if({rv_data[61:54],rv_data[52:45]} == 16'h8100)begin//eth type.                             
                        o_ctag_flag          <= 1'b1;
                        o_replication_flag  <= rv_data[43];
                        ov_ipv              <= iv_ipv;
								//if(rv_data[42] == 1'b0)begin//st
                        //    ov_ipv              <= 3'd5;
                        //end
                        //else begin//rc
                        //    ov_ipv              <= 3'd3;
                        //end
                        ov_inject_dbufid    <= iv_inject_dbufid; 
                        //pjt0621
                        /* 
                        if(rv_data[15+69])begin//replication_flag is 1 means the pkt contains rtag.
                            ov_inject_dbufid    <= rv_data[28+138:24+138]; 
                        end
                        else begin
                            ov_inject_dbufid    <= ov_inject_dbufid;
                        end
                        */
					end 
                    else begin
                        o_ctag_flag          <= 1'b0;
                        o_replication_flag   <= 1'b0;
                        if({rv_data[61:54],rv_data[52:45]} == 16'hff01)begin//tsmp eth type.
                            ov_ipv               <= 3'd2; 
                        end
                        else begin
                            ov_ipv               <= 3'd0; 
                        end                        
					end
                end
				else begin
                    ov_data             <= 9'b0;
                    o_data_wr           <= 1'b0;
                    ov_inject_dbufid    <= 5'b0;
                    ov_ipv              <= 3'b0;
                    o_replication_flag  <= 1'b0;
                    
                    rv_extract_state    <= IDLE_S;             
                end
            end							
            TRAN_PKT_S:begin   
                o_data_wr           <= 1'b1;
                ov_data             <= rv_data[170:162];                  
                if(rv_data[170]) begin   //transmit data.
                    rv_extract_state    <= IDLE_S;                    
                end
                else begin
                    rv_extract_state    <= TRAN_PKT_S;
                end
            end            
            default:begin
                ov_data             <= 9'b0;
                o_data_wr           <= 1'b0;
                ov_inject_dbufid    <= 5'b0;
                ov_ipv              <= 3'b0;
         
                rv_extract_state    <= IDLE_S;  
            end
        endcase
    end
end   
endmodule
